//Class that represents a 32-bit word
//Internaly bit0 is the least significant bit 
//and bit31 is the most significant bit
// 
//The word can be initiated through different constructors
//For output conversions to hexadecimal or binary string are supported

#include "word32.h"

//initiate w to the value given by the input string
//The string hould be encoded with LSB first
//It is also assumed that the length of the string is not longer than 32-bits
//But shorter is ok
word32::word32(std::string inputString){
  //initiate w to 0
  w=0;
  //copy bits from inputString
  for(unsigned i=0;i<inputString.size();i++){
    if(inputString[i]=='1')
      setBit(i);
  }
}

//assign w to the value given by the input string
//The string hould be encoded with LSB first
//It is also assumed that the length of the string is not longer than 32-bits
//But shorter is ok
void word32::assign(std::string inputString){
  //initiate w to 0
  w=0;
  //copy bits from inputString
  for(unsigned i=0;i<inputString.size();i++){
    if(inputString[i]=='1')
      setBit(i);
  }
}

//return the word encoded as a string
//binary representation with the least significant bit first
std::string word32::toBinStringLSB(){
  std::string s;
  uint32_t w2=w; //copy the word
  //extract least significant bit from w2
  //shift to remove least significant bit
  //and repeat for new least significant bit
  for(int i=0;i<32;i++){
    if((w2&1)==0)
      s+='0';
    else
      s+='1';
    w2>>=1;
  }
  return s;
}

//return the word encoded as a string
//binary representation with the most significant bit first
std::string word32::toBinStringMSB(){
  //create w2 as the same word as w but bit ordering reversed
  word32 w2;
  for(int i=0;i<32;i++)
    w2.setVal((31-i),getBit(i));
  //w with MSB first is the same as w2 with LSB
  return w2.toBinStringLSB();
}

//return the word encoded as a string
//hexadecimal representation with the  most significant bit first
std::string word32::toHexStringMSB(){
  std::string s1="0123456789ABCDEF"; //hexadecimal characters
  std::string s2="";
  //mask 4 consecutive bits
  //starting with 4 most significant bits
  s2+=s1[(w>>28)&15]; 
  s2+=s1[(w>>24)&15];
  s2+=s1[(w>>20)&15];
  s2+=s1[(w>>16)&15];
  s2+=s1[(w>>12)&15];
  s2+=s1[(w>>8)&15];
  s2+=s1[(w>>4)&15];
  s2+=s1[(w&15)];
  return s2;
}

//return the word encoded as a string
//hexadecimal representation with the  least significant bit first
std::string word32::toHexStringLSB(){
  //w with MSB first is the same as w2 with LSB  
  word32 w2;
  for(int i=0;i<32;i++)
    w2.setVal((31-i),getBit(i));
  return w2.toHexStringMSB();
}

//calculates the number of 1 in the word
int word32::weight(){
  //using the popcount algorithm to calculate the weight
  uint32_t wht=(w&0x55555555uL)+ ((w>>1)&0x55555555uL); //2-bit
  wht=(wht&0x33333333uL)+ ((wht>>2)&0x33333333uL); //4-bit
  wht=(wht&0x0f0f0f0fuL)+ ((wht>>4)&0x0f0f0f0fuL); //8-bit
  wht=(wht&0x00ff00ffuL)+ ((wht>>8)&0x00ff00ffuL); //16-bit
  wht=(wht&0x0000ffffuL)+ ((wht>>16)&0x0000ffffuL); //32-bit
  return (int)wht;
}
